home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Reference Guide / C-C++ Interactive Reference Guide.iso / c_ref / csource5 / 357_01 / cstar1.exe / OUT.C < prev    next >
C/C++ Source or Header  |  1991-06-18  |  26KB  |  1,355 lines

  1. /*    C* high level output routines.
  2.  
  3.     source:  out.c
  4.     started: February 22, 1989
  5.     version:
  6.         February 22, 1989
  7.         March 8, 1989
  8.  
  9.     PUBLIC DOMAIN SOFTWARE
  10.  
  11.     The CSTAR program was placed in    the public domain on June 15, 1991,
  12.     by its author and sole owner,
  13.  
  14.         Edward K. Ream
  15.         1617 Monroe Street
  16.         Madison, WI 53711
  17.         (608) 257-0802
  18.  
  19.     CSTAR may be used for any commercial or non-commercial purpose.
  20.  
  21.     See cstar.h or cstar.c for a DISCLAIMER OF WARRANTIES.
  22. */
  23.  
  24. #include "cstar.h"
  25.  
  26. extern int sa_push[8];
  27. extern int sd_push[8];
  28. extern struct type_node * intrn_decl;
  29.  
  30. /*
  31.     Externally visible functions
  32. */
  33.  
  34. void out_arg    (struct node * p);
  35. void out_decl    (struct type_node *t);
  36. void out_function    (struct fbody *p, unsigned long link_size,
  37.             int r_push, int do_addq);
  38. void out_list    (register struct node *p);
  39. void out_tree    (struct node * p);
  40.  
  41. /*
  42.     Internal functions
  43. */
  44. static void out_init    (struct iblock *ibp, char *name);
  45. static void out_loc    (register struct node *p);
  46. static void out_rlist    (void);
  47. static void out_seg    (int seg);
  48. static void out_strs    (char *name, char *s, unsigned long dim);
  49.  
  50. /*
  51.     Part I:  ----- Code Generation Output Routines -----
  52. */
  53.  
  54. /*
  55.     Output code for segment declaration if there is a change
  56. */
  57. static void
  58. out_seg(int seg)
  59. {
  60.     if (seg == segment) {
  61.         return;
  62.     }
  63.     segment = seg;
  64.     switch(seg) {
  65.     case S_BSS:
  66.         syssput(".bss");
  67.         break;
  68.     case S_DATA:
  69.         syssput(".data");
  70.         break;
  71.     case S_TEXT:
  72.         syssput(".text");
  73.         break;
  74.     default:
  75.         g_error(NULL, "internal: out_seg: bad segment");
  76.     }
  77.     sysnlput();
  78. }
  79.  
  80. /*
  81.     Output or generate code for a list of definitions/declarations.
  82.  
  83.     WARNING:  no code generation (auto initializers) yet.
  84. */
  85. void
  86. out_decl(struct type_node *t)
  87. {
  88.     register int class;
  89.     register char *name;
  90.     register struct st_node *id;
  91.     unsigned long size;
  92.     char buf[LONG_DIGITS];
  93.  
  94.     TICK("out_decl");
  95.  
  96.     if (nogen_flag) {
  97.         /* Suppress code generation and output. */
  98.         return;
  99.     }
  100.     while (t && t -> t_typtok == DELEMENT_TYPE) {
  101.         id = t -> t_parent;
  102.         if (id == NULL) {
  103.             switch (t -> t_link -> t_typtok) {
  104.             default:
  105.                 t_error("internal: no decl parent");
  106.             case STRUCT_TYPE:
  107.             case UNION_TYPE:
  108.                 ;
  109.             }
  110.             t = t -> t_list;
  111.             continue;
  112.         }
  113.         class = id -> st_sclass;
  114.         /* CAUTION: name may be junk for register class */
  115.         name = id -> st_alias;
  116.         size = t -> t_link -> t_tsize;
  117.  
  118.         switch (class) {
  119.         /* NOTE: initialized globals go into the data segment
  120.             and get set up with dc directives */
  121.         case AUTO_CLASS:
  122.         case REGISTER_CLASS:
  123.             if (id -> st_iniz) {
  124.                 g_error(NULL, "register/auto init not ready yet");
  125.             }
  126.             /* FALLTHROUGH */
  127.  
  128.         case FORMAL_CLASS:
  129.         case FORMREG_CLASS:
  130.             /* output explanatory comment */
  131.             syssput("*\t");
  132.             syssput(id -> st_name);
  133.             if (id -> st_offset) {
  134.                 syssput(" = ");
  135.                 convl2s(id -> st_offset, buf);
  136.                 syssput(buf);
  137.             }
  138.             if (id -> st_misc & ST_REG) {
  139.                 syssput(" = ");
  140.                 syssput(arp_tab[id -> st_misc & ST_REG]);
  141.             }
  142.             sysnlput();
  143.             break;
  144.  
  145.         case EXTERN_CLASS:
  146.             syssput(".globl ");
  147.             syssput(name);
  148.             sysnlput();
  149.             break;
  150.  
  151.         case STATICL_CLASS:
  152.             /* output explanatory comment */
  153.             syssput("*\t");
  154.             syssput(id -> st_name);
  155.             syssput(" = ");
  156.             syssput(name);
  157.             sysnlput();
  158.             /* FALLTHROUGH */
  159.  
  160.         case STATICG_CLASS:
  161.             if (id -> st_iniz) {
  162.                 out_seg(S_DATA);
  163.                 out_init(id -> st_iniz, name);
  164.             }
  165.             else {
  166.                 out_seg(S_BSS);
  167.                 syssput(name);
  168.                 syssput(":\tds.b ");
  169.                 convl2s(size, buf);
  170.                 syssput(buf);
  171.                 sysnlput();
  172.             }
  173.             break;
  174.  
  175.         case GLOBAL_CLASS:
  176.             out_seg(S_DATA);
  177.             syssput(".globl ");
  178.             syssput(name);
  179.             sysnlput();
  180.  
  181.             if (id -> st_iniz) {
  182.                 out_init(id -> st_iniz, name);
  183.             }
  184.             else {
  185.                 syssput(".comm ");
  186.                 syssput(name);
  187.                 syscput(',');
  188.                 convl2s(size, buf);
  189.                 syssput(buf);
  190.                 sysnlput();
  191.             }
  192.             break;
  193.             
  194.         default:
  195.             t_error("internal: out_decl: unknown class");
  196.  
  197.         case CODE_CLASS:
  198.         case SCODE_CLASS:
  199.         case TAG_CLASS:
  200.         case TYPEDEF_CLASS:
  201.             ;
  202.         }
  203.         t = t -> t_list;
  204.     }
  205. }
  206.  
  207. /*
  208.     output a memory initializer, which means into the data segment
  209.     this is for statics and globals
  210.  
  211.     it is of course useless for auto variables, for which the
  212.     initialization must actually generate code
  213.  
  214.     t is a DELEMENT node
  215. */
  216. #define LINELEN 70
  217.  
  218. static void
  219. out_init(struct iblock *ibp, char *name)
  220. {
  221.     register unsigned long i;
  222.     register int n, f, l;
  223.     register struct iblock *p, *q;
  224.     register unsigned char *s;
  225.     unsigned char buf[LONG_DIGITS];
  226.  
  227.     TICK("out_init");
  228.  
  229.     p = ibp;
  230.  
  231. #ifdef DEBUG
  232.     if (p == NULL) {
  233.         g_error(NULL, "internal: out_init: no block");
  234.     }
  235. #endif
  236.     while(p) { 
  237.     switch(p -> itype) {
  238.     case 0:
  239.         buf[0] = '$';
  240.         f = FALSE;
  241.         for (n = LINELEN + 1, i = 0; i < p -> idim; i++) {
  242.             /*
  243.                 CAUTION:
  244.                 if you wish for this to output in hex,
  245.                 you MUST truncate the data to the 
  246.                 appropriate width; otherwise, a byte -1
  247.                 will be output as $FFFFFFFF
  248.             */
  249.             if (q = (struct iblock* ) p -> idata[i] . ipt) {
  250.                 switch (q -> itype) {
  251.                 case ISTRS_DEC:
  252.                     s = (void *) q -> idata[1] . ipt;
  253.                     break;
  254.                 case ITAG_DEC:
  255.                     s = (void *) q -> idata[0] . ipt;
  256.                     break;
  257.                 default:
  258.                     g_error(NULL, "internal: out_init: unknown iblock type");
  259.                 }
  260.             }
  261.             else {
  262.                 convl2s(p -> idata [i] . icn, &buf[1]);
  263.                 s = &buf[1]; /* leave off $ for decimal */
  264.             }
  265.             l = str_len(s);
  266.             if (n + l > LINELEN) {
  267.                 /* essentially, issue a line */
  268.                 f = FALSE;
  269.                 n = 5;
  270.                 if (name) {
  271.                     syssput(name);
  272.                     syscput(':');
  273.                     if (str_len(name) >= 7) {
  274.                         n += 8;
  275.                     }
  276.                     name = NULL;
  277.                 }
  278.                 else if (i) {
  279.                     sysnlput();
  280.                 }
  281.                 switch (p -> isize) {
  282.                 case 1:
  283.                     syssput("\tdc.b ");
  284.                     break;
  285.                 case 2:
  286.                     syssput("\tdc.w ");
  287.                     break;
  288.                 case 4:
  289.                     syssput("\tdc.l ");
  290.                     break;
  291.                 default:
  292.                     g_error(NULL, "internal: out_init: bad size");
  293.                 }
  294.             }
  295.             else {
  296.                 if (f) {
  297.                     syscput(',');
  298.                     n++;
  299.                 }
  300.             }
  301.             f = TRUE;
  302.             n += l;
  303.             syssput(s);
  304.         }  /* end for */
  305.  
  306.         /* end block */
  307.         break;
  308.  
  309.     case IBSSZB_DEC:
  310.         conul2sc(p -> idim, buf, 1);
  311.         syssput("\tds.b ");
  312.         syssput(buf);
  313.         break;
  314.  
  315.     case ISTRA_DEC:
  316.         out_strs( name,
  317.               (char *) p -> idata[0] . ipt,
  318.               (unsigned long) p -> idim);
  319.         break;
  320.  
  321.     default:
  322.         g_error(NULL, "internal: out_init: unknown block in series");
  323.     }  /* end switch */
  324.     sysnlput();
  325.  
  326.     p = p -> ilink;
  327.     } /* end while */
  328.  
  329.     /* now reiterate the loop to output secondary declarators */
  330.     p = ibp;
  331.     while (p) {
  332.         if (p -> itype == 0) {
  333.             for (i = 0; i < p -> idim; i++) {
  334.                 if (q = (struct iblock *)p->idata[i].ipt)
  335.                 switch(q -> itype) {
  336.                 case ISTRS_DEC:
  337.                     out_strs( (char *) q -> idata[1] . ipt, 
  338.                           (char *) q -> idata[0] . ipt,
  339.                           (unsigned long)  q -> idim);
  340.                     sysnlput();
  341.                 }
  342.             }
  343.         }
  344.         p = p -> ilink;
  345.     }
  346. }
  347.  
  348. /*
  349.     output a string-array declarator
  350. */
  351. static void
  352. out_strs(char *name, char *s, unsigned long dim)
  353. {
  354.     register unsigned long i;
  355.     int f, n, l;
  356.     unsigned char buf[LONG_DIGITS];
  357.  
  358.     f = 0;
  359.     buf[0] = '$';
  360.     for (n = LINELEN + 1, i = 0; ; i++) {
  361.         /* deal with chars one at a time */
  362.         if (n > LINELEN - 5) {
  363.             if (f & 2) {
  364.                 /* close quote before initiating line */
  365.                 syscput('\"');
  366.             }
  367.             if (name) {
  368.                 syssput(name);
  369.                 syscput(':');
  370.                 name = NULL;
  371.             }
  372.             else if (i) {
  373.                 sysnlput();
  374.             }
  375.             syssput("\tdc.b ");
  376.             n = 5;
  377.         }
  378.         if (s[i] >= ' ' && s[i] < 0x7f && s[i] != '\"') {
  379.             /* printable */
  380.             if (!(f & 2)) {
  381.                 /* flip to printable (quote mode) */
  382.                 if (f & 1) {
  383.                     syscput(',');
  384.                     n++;
  385.                 }
  386.                 syscput('\"');
  387.                 f |= 2;
  388.                 n++;
  389.             }
  390.             syscput(s[i]);
  391.         }
  392.         else {
  393.             if (f & 2) {
  394.                 /* flip to nonprintable */
  395.                 syscput('\"');
  396.                 f ^= 2;
  397.                 n++;
  398.             }
  399.             if (f & 1) {
  400.                 syscput(',');
  401.                 n++;
  402.             }
  403.             conl2h( (unsigned long) s[i], &buf[1], 1);
  404.             syssput(buf);
  405.             n += str_len(buf);
  406.         }
  407.         f |= 1;        /* char out so flag comma required */
  408.         if (i + 1 >= dim) {
  409.             /* close any quote and exit */
  410.             if (f & 2) {
  411.                 syscput('\"');
  412.             }
  413.             break;
  414.         }
  415.     } /* end for */
  416. }
  417.  
  418. /* actual file output */
  419. void
  420. out_function(struct fbody *p, unsigned long link_size, int r_push, int do_addq)
  421. {
  422.     char buf[LONG_DIGITS];
  423.  
  424.     /* output the function header */
  425.     syssput("** function ");
  426.     syssput(p -> fname);
  427.     sysnlput();
  428.  
  429.     /* output the strings and block decls */
  430.     out_decl(intrn_decl);
  431.  
  432.     if (p -> fclass == CODE_CLASS) {
  433.         syssput(".globl ");    /* declaration of the function name */
  434.         syssput(p -> fname);
  435.         sysnlput();
  436.     }
  437.  
  438.     out_decl(p -> formals);    /* definition of the formals */
  439.     out_decl(p -> locals);    /* and the locals */
  440.     out_seg(S_TEXT);
  441.     syssput(p -> fname);    /* label for the first instruction in the fn */
  442.     syscput(':');
  443.     sysnlput();
  444.  
  445.     /* Output the entry code. */
  446.     if (link_size || p -> fml_size) {
  447.         conul2sc(link_size, buf, 1);
  448.         if (link_size < 32768L) {
  449.             syssput("\tlink a6,#-");
  450.             syssput(buf);
  451.             sysnlput();
  452.         }
  453.         else {
  454.             syssput("\tmove.l a6,-(a7)");
  455.             sysnlput();
  456.             syssput("\tmove.l a7,a6");
  457.             sysnlput();
  458.             syssput("\tsuba.l #");
  459.             syssput(buf);
  460.             syssput(",a7");
  461.             sysnlput();
  462.         }
  463.     }
  464.  
  465.     /* output the register saves */
  466.     if (r_push) {
  467.         syssput("\tmovem.l\t");
  468.         out_rlist();
  469.         syssput(",-(a7)");
  470.         sysnlput();
  471.     }
  472.     if (do_addq) {
  473.         syssput("\tsubq.l #4, a7");
  474.     }
  475.  
  476.     /*
  477.         Call the peep hole optimizer.
  478.         The nopeep_flag disables the peephole,
  479.         so there is no need for a before and after picture.
  480.     */
  481.     if (!nopeep_flag) {
  482.         if (code1_flag) {
  483.             sysnlput();
  484.             syssput("* >>>>> code prior to peephole:");
  485.             sysnlput();
  486.             sysnlput();
  487.             out_list(code_head);
  488.             sysnlput();
  489.         }
  490.         peep_hole();
  491.  
  492.         if (code2_flag) {
  493.             sysnlput();
  494.             syssput("* >>>>> code after peephole:");
  495.             sysnlput();
  496.             sysnlput();
  497.             /* Print function name for reference. */
  498.             syssput(p -> fname);
  499.             syscput(':');
  500.             sysnlput();
  501.         }
  502.     }
  503.  
  504.     /* output the code list */
  505.     out_list(code_head);
  506.  
  507.     /* output the register restores and actual exit */
  508.     if (do_addq) {
  509.         syssput("\taddq.l #4,a7");
  510.         sysnlput();
  511.     }
  512.     if (r_push) {
  513.         syssput("\tmovem.l\t");
  514.         syssput("(a7)+,");
  515.         out_rlist();
  516.         sysnlput();
  517.     }
  518.     if (link_size || p -> fml_size) {
  519.         if (link_size < 32768L) {
  520.             syssput("\tunlk a6");
  521.             sysnlput();
  522.         }
  523.         else {
  524.             syssput("\tmove.l a6,a7");
  525.             sysnlput();
  526.             syssput("\tmove.l (a7)+,a6");
  527.             sysnlput();
  528.         }
  529.     }
  530.     syssput("\trts");
  531.     sysnlput();
  532. }
  533.  
  534. static void
  535. out_rlist(void)
  536. {
  537.     register int i, f;
  538.  
  539.     f = FALSE;
  540.     for (i = 0; i <= 7; i++) {
  541.         if (sd_push[i]) {
  542.             if (f) {
  543.                 syscput('/');
  544.             }
  545.             syssput(arp_tab[d_reg(i)]);
  546.             f = TRUE;
  547.         }
  548.     }
  549.     for (i = 0; i <= 7; i++) {
  550.         if (sa_push[i]) {
  551.             if (f) {
  552.                 syscput('/');
  553.             }
  554.             syssput(arp_tab[a_reg(i)]);
  555.             f = TRUE;
  556.         }
  557.     }
  558. }
  559.  
  560. /*
  561.     Part II:  ----- Output routines to dump parse trees  -----
  562. */
  563. static void    out_expr(struct node *p);
  564. static void    out_stat(struct node *p);
  565. static void    out_stat(struct node *p);
  566. static void    out_type(struct type_node *p);
  567. static void    out_1type(struct type_node *t, bool usexpand, bool fnexpand);
  568.  
  569. /*
  570.     Print a list of parse nodes.
  571.  
  572.     See the file par.h for the definitions of these nodes.
  573. */
  574. void
  575. out_tree(struct node * p)
  576. {
  577.     register int i;
  578.     register int type;
  579.     register struct type_node *id;
  580.     register struct node *q;
  581.     char buffer [100];
  582.  
  583.     SL_DISABLE();
  584.  
  585.     if (p == NULL) {
  586.         syssput("<NO CODE LIST>");
  587.         sysnlput();
  588.         return;
  589.     }
  590.  
  591.     do {
  592.  
  593.     switch (p -> n_type) {
  594.  
  595.     case CALL_TOK:
  596.         syssput("CALL[");
  597.         out_expr(p -> n_arg1);
  598.         syssput(",");
  599.         sysnlput();
  600.         syssput("[");
  601.         out_expr(p -> n_arg2);
  602.         syssput("]]");
  603.         sysnlput();
  604.         break;
  605.  
  606.     case Z_TOK:
  607.         sprintf(&buffer[0], "pseudo: %s: ", xzp_tab [p -> n_ztype]);
  608.         syssput(buffer);
  609.         out_expr(p -> n_zarg1);
  610.         sysnlput();
  611.         break;
  612.  
  613.     case X_TOK:
  614.         type = p -> n_xtype;
  615.         sprintf(&buffer[0], "x_tok: %s(", xzp_tab [type]);
  616.         syssput(buffer);
  617.         if (type == X_BRA || type == X_BSR || is_bxx(type)) {
  618.                    syssput("label: ");
  619.             syssput(p -> n_arg1 -> c_labsym);
  620.         }
  621.         else if (is_dbxx(type)) {
  622.             out_expr(p -> n_xarg1);
  623.             syssput(",label: ");
  624.             syssput(p -> n_arg2 -> c_labsym);
  625.         }
  626.         else if (type == X_JMP || type == X_JSR) {
  627.             if (p -> n_xarg1) {
  628.                 out_expr(p -> n_xarg1);
  629.             }
  630.             if (p -> n_arg2) {
  631.                 syssput("label: ");
  632.                 syssput(p -> n_arg2 -> c_labsym);
  633.             }
  634.         }
  635.         else if (p -> n_xarg1) {
  636.             out_expr(p -> n_xarg1);
  637.             if (p -> n_xarg2) {
  638.                 syssput(", ");
  639.                 out_expr(p -> n_xarg2);
  640.             }
  641.         }
  642.         syssput(")");
  643.         sysnlput();
  644.         break;
  645.  
  646.     case K_IF:
  647.         syssput("if (");
  648.         out_expr(p -> n_ibool);
  649.         syssput(")");
  650.         sysnlput();
  651.         out_stat(p -> n_ithen);
  652.         sysnlput();
  653.         if (p -> n_ielse) {
  654.             syssput("else ");
  655.             out_stat(p -> n_ielse);
  656.             sysnlput();
  657.         }
  658.         break;
  659.  
  660.     case K_DO:
  661.         syssput("do ");
  662.         out_stat(p -> n_dbdy);
  663.         syssput(" while (");
  664.         out_expr(p -> n_dbool);
  665.         syssput(")");
  666.         sysnlput();
  667.         break;
  668.  
  669.     case K_WHILE:
  670.         syssput("while (");
  671.         out_expr(p -> n_wbool);
  672.         syssput(")");
  673.         out_stat(p -> n_wbdy);
  674.         sysnlput();
  675.         break;
  676.  
  677.     case K_FOR:
  678.         syssput("for(");
  679.         out_tree(p -> n_f1list);
  680.         syssput(";");
  681.         out_expr(p -> n_fbool);
  682.         syssput(";");
  683.         out_tree(p -> n_f2list);
  684.         syssput(") ");
  685.         out_stat(p -> n_fbdy);
  686.         sysnlput();
  687.         break;
  688.  
  689.     case K_SWITCH:
  690.         syssput("switch(");
  691.         out_expr(p -> n_sval);
  692.         syssput(") ");
  693.         out_stat(p -> n_sbdy);
  694.         sysnlput();
  695.         break;        
  696.  
  697.     case K_BREAK:
  698.         syssput("break;");
  699.         sysnlput();
  700.         break;
  701.  
  702.     case K_CONTINUE:
  703.         syssput("continue;");
  704.         sysnlput();
  705.         break;
  706.  
  707.     case K_CASE:
  708.         sprintf(&buffer[0], "case %ld:", p -> n_ccon);
  709.         syssput(buffer);
  710.         sysnlput();
  711.         break;
  712.  
  713.     case K_DEFAULT:
  714.         syssput("default:");
  715.         sysnlput();
  716.         break;
  717.  
  718.     case K_RETURN:
  719.         syssput("return");
  720.         if (p -> n_rval) {
  721.             syssput("(");
  722.             out_expr(p -> n_rval);
  723.             syssput(")");
  724.         }
  725.         syssput(";");
  726.         sysnlput();
  727.         break;
  728.  
  729.     case LABEL_TOK:
  730.         syssput("<LABEL> ");
  731.         syssput(p -> n_plab -> c_labsym);
  732.         syssput(":");
  733.         sysnlput();
  734.         break;
  735.  
  736.     case K_GOTO:
  737.         syssput("goto ");
  738.         syssput(p -> n_plab -> c_labsym);
  739.         syssput(";");
  740.         sysnlput();
  741.         break;
  742.  
  743.     /* uop_node and binop_node */
  744.     default:
  745.  
  746.         i = p -> n_type;
  747.         if (is_op(i) || i == ID_TOK) {
  748.             out_expr(p);
  749.             sysnlput();
  750.         }
  751.         else {
  752.             sprintf(&buffer[0], "<INAPPROPRIATE NODE %d>",
  753.                 p -> n_type);
  754.             syssput(buffer);
  755.             sysnlput();
  756.         }
  757.         break;
  758.     } /* end switch */
  759.     } /* end dowhile */
  760.     while ( (p = p -> n_next) != NULL);
  761. }
  762.  
  763. /*
  764.     Print an expression.
  765.     See the file par.h for the definitions of these nodes.
  766. */
  767. static void
  768. out_expr(register struct node * p)
  769. {
  770.     register struct st_node * id;
  771.     register int i;
  772.     char buffer [100];
  773.  
  774.     TICK("out_expr");
  775.     if (p == NULL) {
  776.         syssput("<NULL>");
  777.         return;
  778.     }
  779.  
  780.     switch (p -> n_type) {
  781.  
  782.     case ID_TOK:
  783.         if (p -> n_cid != NULL) {
  784.             id = p -> n_cid;
  785.             if ((long)id & 1) {
  786.                 sprintf(&buffer[0], "id: <%p>", id);
  787.                 syssput(buffer);
  788.             }
  789.             else {
  790.                 sprintf(&buffer[0], "id: %s", id -> st_name);
  791.                 syssput(buffer);
  792.             }
  793.         }
  794.         else if (p -> n_reg1) {
  795.             sprintf(&buffer[0], "reg: %s", arp_tab[p -> n_reg1]);
  796.             syssput(buffer);
  797.         }
  798.         else if (p -> n_cltype != NULL) {
  799.             switch( (p -> n_cltype) -> t_typtok) {
  800.  
  801.             case INT_TYPE:
  802.                 i = p -> n_cltype -> t_mclass;
  803.                 if (i & UNSIGNED_MOD) {
  804.                     syssput("(u ");
  805.                 }
  806.                 else {
  807.                     syssput("(s ");
  808.                 }
  809.  
  810.                 if (i & LONG_MOD) {
  811.                     syssput("long)");
  812.                 }
  813.                 else if (i & SHORT_MOD) {
  814.                     syssput("short)");
  815.                 }
  816.                 else if (i & CHAR_MOD) {
  817.                     syssput("char)");
  818.                 }
  819.                 else {
  820.                     syssput("int)");
  821.                 }
  822.  
  823.                 if (i & UNSIGNED_MOD) {
  824.                     sprintf(&buffer[0], "%lu", p -> n_const);
  825.                     syssput(buffer);
  826.                 }
  827.                 else {
  828.                     sprintf(&buffer[0], "%ld", p -> n_const);
  829.                     syssput(buffer);
  830.                 }
  831.                 break;
  832.  
  833.             case SELEMENT_TYPE:
  834.             case UELEMENT_TYPE:
  835.             case DELEMENT_TYPE:
  836.                 sprintf(&buffer[0], "(elt) %lu", p -> n_const);
  837.                 syssput(buffer);
  838.                 break;
  839.  
  840.             case ARRAY_TYPE:
  841.                 /* one should possibly check further */
  842.                 sprintf(&buffer[0], "\"%s\"", p -> n_const);
  843.                 syssput(buffer);
  844.                 break;
  845.  
  846.             case POINTER_TYPE:
  847.                 sprintf(&buffer[0], "(pointer)%ld", p -> n_const);
  848.                 syssput(buffer);
  849.                 break;
  850.  
  851.             default:
  852.                 sprintf(&buffer[0], "%ld<unknown type>", p -> n_const);
  853.                 syssput(buffer);
  854.                 break;
  855.             }
  856.         }
  857.         else {
  858.             sprintf(&buffer[0], "%ld<missing type>", p -> n_const);
  859.             syssput(buffer);
  860.         }
  861.         break;
  862.  
  863.     case CALL_TOK:
  864.         syssput("CALL[");
  865.         out_expr(p -> n_arg1);
  866.         syssput(",");
  867.         sysnlput();
  868.         syssput("[");
  869.         out_expr(p -> n_arg2);
  870.         syssput("]]");
  871.         break;
  872.  
  873.     case CC_TOK:
  874.         sprintf(&buffer[0], "cc: %s", arp_tab [p -> n_xtype]);
  875.         syssput(buffer);
  876.         break;
  877.  
  878.     case SEPARATOR_TOK:
  879.         out_expr(p -> n_car);
  880.         syssput(" @ ");
  881.         sysnlput();
  882.         out_expr(p -> n_next); /* n_next acts like n_arg2? */
  883.         break;
  884.  
  885.     case K_CHAR:
  886.     case K_INT:
  887.     case K_LONG:
  888.     case K_STRUCT:
  889.     case K_UNION:
  890.     case K_TYPEDEF:
  891.         syssput("out_expr: what is this??");
  892.         sysnlput();
  893.         out_type((struct type_node *)p);
  894.         break;
  895.  
  896.     case QUESTION_TOK:
  897.         /* Ternary OP. */
  898.         syssput("?:[");
  899.         out_expr(p -> n_arg1);
  900.         syssput(",");
  901.         sysnlput();
  902.         out_expr(p -> n_arg2);
  903.         syssput(",");
  904.         sysnlput();
  905.         out_expr(p -> n_arg3);
  906.         syssput("]");
  907.         break;
  908.  
  909.     /* uop_node and binop_node */
  910.     default:
  911.  
  912.         i = p -> n_type;
  913.         if (is_op(i)) {
  914.             syssput(ps_tok(i));
  915.             if (is_unop(i)) {
  916.                 /* Unary OP. */
  917.                 if (i == CAST_TOK) {
  918.                     syssput("(");
  919.                     out_1type(p -> n_cltype, TRUE, TRUE);
  920.                     syssput(")");
  921.                 }
  922.                 syssput("[");
  923.                 out_expr(p -> n_arg1);
  924.                 syssput("]");
  925.             }
  926.             else {
  927.                 /* Binary OP. */
  928.                 syssput("[");
  929.                 out_expr(p -> n_arg1);
  930.                 syssput(",");
  931.                 sysnlput();
  932.                 out_expr(p -> n_arg2);
  933.                 syssput("]");
  934.             }
  935.         }
  936.         else {
  937.             sprintf(&buffer[0],
  938.             "node \"%s\" (%d) doesn't belong in expression",
  939.                 ps_tok(i), i);
  940.             syssput(buffer);
  941.             sysnlput();
  942.         }
  943.     } /* (end switch) */
  944. }
  945.  
  946. /*
  947.     Print a statement list enclosed in curly braces.
  948. */
  949. static void
  950. out_stat(struct node * p)
  951. {
  952.     syssput("{");
  953.     if (p != NULL) {
  954.         sysnlput();
  955.         out_tree(p);
  956.     }
  957.     syssput("}");
  958. }
  959.  
  960. /*
  961.     Print a type.
  962. */
  963. static void
  964. out_type(struct type_node *t)
  965. {
  966.     TICK("prtype");
  967.     out_1type(t, TRUE, TRUE);
  968.     sysnlput();
  969. }
  970.  
  971. static void
  972. out_1type(register struct type_node * t, bool usexpand, bool fnexpand)
  973. {
  974.     int i;
  975.     char buffer [100];
  976.  
  977.     for(;;) {
  978.         if (t == NULL) {
  979.             syssput("<NO TYPE>");
  980.             return;
  981.         }
  982.  
  983.         /* first the primary printout */
  984.         i = t -> t_typtok;
  985.         if (t -> t_mclass & CONST_MOD) {
  986.             syssput("const ");
  987.         }
  988.         if (t -> t_mclass & VOLATILE_MOD) {
  989.             syssput("volatile ");
  990.         }
  991.         switch (i) {
  992.         case NULL_TYPE:
  993.             syssput("NULLtype");
  994.             return;
  995.  
  996.         case BOOL_TYPE:
  997.         case FLOAT_TYPE:
  998.         case INT_TYPE:
  999.         case VOID_TYPE:
  1000.             if (t -> t_mclass & UNSIGNED_MOD) {
  1001.                 syssput("unsigned ");
  1002.             }
  1003.             if (t -> t_mclass & CHAR_MOD) {
  1004.                 if (!(t -> t_mclass & UNSIGNED_MOD)) {
  1005.                     syssput("signed ");
  1006.                 }
  1007.                 syssput("char");
  1008.             }
  1009.             if (t -> t_mclass & SHORT_MOD) {
  1010.                 syssput("short ");
  1011.             }
  1012.             if (t -> t_mclass & LONG_MOD) {
  1013.                 syssput("long ");
  1014.             }
  1015.             break;
  1016.  
  1017.         case ARRAY_TYPE:
  1018.             sprintf(&buffer[0], "array [%ld] of ", t -> t_tdim);
  1019.             syssput(buffer);
  1020.             break;
  1021.  
  1022.         case FUNCTION_TYPE:    syssput("function");        break;
  1023.         case POINTER_TYPE:    syssput("pointer to ");        break;
  1024.         case CAST_TYPE:        syssput("cast into ");        break;
  1025.  
  1026.         case STRUCT_TYPE:
  1027.             sprintf(&buffer[0], "struct %p {%ld}:",
  1028.                 t, t -> t_tsize);
  1029.             syssput(buffer);
  1030.             break;
  1031.  
  1032.         case UNION_TYPE:
  1033.             sprintf(&buffer[0], "union %p {%ld}:",
  1034.                 t, t -> t_tsize);
  1035.             syssput(buffer);
  1036.             break;
  1037.  
  1038.         case DECL_TYPE:
  1039.             sprintf(&buffer[0], "DECL <%ld>:", t -> t_tsize);
  1040.             syssput(buffer);
  1041.             sysnlput();
  1042.             break;
  1043.  
  1044.         case DELEMENT_TYPE:
  1045.             syssput("delement--");
  1046.             break;
  1047.  
  1048.         case SELEMENT_TYPE:
  1049.             syssput("  selement--");
  1050.             break;
  1051.  
  1052.         case UELEMENT_TYPE:
  1053.             syssput("  uelement--");
  1054.             break;
  1055.  
  1056.         default:
  1057.             sprintf(&buffer[0], "out_type: unknown type %d", t -> t_typtok);
  1058.             syssput(buffer);
  1059.             return;
  1060.         }
  1061.  
  1062.         /* then further explanation and linkage */
  1063.         switch (i) {
  1064.         case DECL_TYPE:
  1065.             t = t -> t_list;
  1066.             break;
  1067.  
  1068.         case FUNCTION_TYPE:
  1069.             if (t -> t_list == NULL) {
  1070.                 syssput(" returning ");
  1071.             }
  1072.             else {
  1073.                 syssput("--");
  1074.                 sysnlput();
  1075.                 out_1type(t -> t_list, usexpand, FALSE);
  1076.                 sysnlput();
  1077.                 syssput("--which returns ");
  1078.             }
  1079.             t = t -> t_link;
  1080.             break;
  1081.  
  1082.         case STRUCT_TYPE:
  1083.         case UNION_TYPE:
  1084.             if (t -> t_list == NULL) {
  1085.                 syssput(" <NO LIST>");
  1086.             }
  1087.             else if (usexpand) {
  1088.                 sysnlput();
  1089.                 out_1type(t -> t_list, FALSE, fnexpand);
  1090.             }
  1091.             else {
  1092.                 syssput(" ...");
  1093.             }
  1094.             return;
  1095.  
  1096.         case DELEMENT_TYPE:
  1097.         case SELEMENT_TYPE:
  1098.         case UELEMENT_TYPE:
  1099.             if (t -> t_parent) {
  1100.                 if (t -> t_parent -> st_name) {
  1101.                     syssput(t -> t_parent -> st_name);
  1102.                     syssput(" ");
  1103.                     if (t -> t_parent -> st_alias) {
  1104.                         syssput(t -> t_parent -> st_alias);
  1105.                     }
  1106.                 }
  1107.                 sprintf(&buffer[0], "@%ld: ",
  1108.                     t -> t_parent -> st_offset);
  1109.                 syssput(buffer);
  1110.             }
  1111.             out_1type(t -> t_link, usexpand, fnexpand);
  1112.             t = t -> t_list;
  1113.             if (t == NULL) {
  1114.                 return;
  1115.             }
  1116.             if (t -> t_typtok != i) {
  1117.                 syssput("<t_list structure error>");
  1118.             }
  1119.             sysnlput();
  1120.                         break;
  1121.  
  1122.         case ARRAY_TYPE:
  1123.         case POINTER_TYPE:
  1124.             t = t -> t_link;
  1125.             break;
  1126.  
  1127.         case BOOL_TYPE:        syssput("bool");    return;
  1128.         case VOID_TYPE:        syssput("void");    return;
  1129.  
  1130.         case INT_TYPE:
  1131.             if (!(t -> t_mclass & CHAR_MOD)) {
  1132.                 syssput("int");
  1133.             }
  1134.             if (t -> t_link) {
  1135.                 sprintf(&buffer[0], "<<error> link=%p>",
  1136.                     t->t_link);
  1137.                 syssput(buffer);
  1138.             }
  1139.             return;
  1140.  
  1141.         case FLOAT_TYPE:
  1142.             syssput("float");
  1143.             return;
  1144.  
  1145.         default:
  1146.             syssput("out_type: internal");
  1147.             sysnlput();
  1148.             return;
  1149.         }
  1150.     }
  1151. }
  1152.  
  1153. /*
  1154.     Part III: ----- Output routines to dump code nodes -----
  1155. */
  1156.  
  1157. /*
  1158.     Go down the global code list and output code.
  1159. */    
  1160. void
  1161. out_list(register struct node *p)
  1162. {
  1163.     register int type;  
  1164.     char buffer [40];
  1165.  
  1166.     TICK("out_list");
  1167.  
  1168.     for(; p; p = p -> c_next) {
  1169.         type = p -> c_code;
  1170.         if (is_xtok(type)) {
  1171.  
  1172.             /* Output machine code to file. */
  1173.             syscput('\t');
  1174.             syssput(xzp_tab [type]);
  1175.  
  1176.             if (p -> c_len1) {
  1177.                 syssput(xlentab[p -> c_len1]);
  1178.             }
  1179.  
  1180.             /* Output 0, 1 or 2 arguments. */
  1181.             if (p -> c_arg1) {
  1182.                 syscput('\t');
  1183.                 out_arg(p -> c_arg1);
  1184.             }
  1185.             if (p -> c_arg2) {
  1186.                 if (!(p -> c_arg1)) {
  1187.                     syscput('\t');
  1188.                     syssput("<NULL>");
  1189.                 }
  1190.                 syscput(',');
  1191.                 out_arg(p -> c_arg2);
  1192.             }
  1193.         }
  1194.         else if (is_ztok(type)) {
  1195.             /* Output pseudo op to file. */
  1196.             syscput('\t');
  1197.             syssput(xzp_tab [type]);
  1198.         }
  1199.         else {
  1200.             switch (type) {
  1201.             case O_LITERAL:
  1202.                 out_arg(p);
  1203.                 break;
  1204.  
  1205.             case O_LINENUM:
  1206.                 syssput("* ----- line ");
  1207.                 conv2s(p -> c_linenum, buffer);
  1208.                 syssput(buffer);
  1209.                 break;
  1210.  
  1211.             case O_LABEL:
  1212.             case O_ULABEL:
  1213.                 out_arg(p);
  1214.                 syscput(':');
  1215.                 break;
  1216.  
  1217.             default:
  1218.                 g_error(NULL, "unknown code type");
  1219.  
  1220.                 /* Include error message in the file. */
  1221.                 syssput("* unknown code type: ");
  1222.                 conv2s(type, buffer);
  1223.                 syssput(buffer);
  1224.             }
  1225.         }
  1226.     sysnlput();
  1227.     }
  1228. }
  1229.  
  1230. /*
  1231.     Output an argument, which is a label or a loc_node.
  1232. */
  1233. void
  1234. out_arg(struct node * p)
  1235. {
  1236.     char buffer [40];
  1237.     struct st_node *id;
  1238.     /* WARNING: the label nodes and the id nodes aren't the same kind */
  1239.  
  1240.     TICK("out_arg");
  1241.  
  1242.     if (p == NULL) {
  1243.         return;
  1244.     }
  1245.  
  1246.     switch(p -> c_code) {
  1247.  
  1248.     case O_LABEL:
  1249.         syscput('L');
  1250.         conv2s(p -> c_labnum, buffer);
  1251.         syssput(buffer);
  1252.         return;
  1253.  
  1254.     case O_ULABEL:
  1255.         /* Output internal label to file. */
  1256.         if (p -> c_labnum) {
  1257.             syscput('U');
  1258.             conv2s(p -> c_labnum, buffer);
  1259.             syssput(buffer);
  1260.         }
  1261.         else {
  1262.             syssput(p -> c_labsym);
  1263.         }
  1264.         break;
  1265.  
  1266.     case O_LITERAL:
  1267.         syssput(p -> c_lit);
  1268.         return;
  1269.  
  1270.     case ID_TOK:
  1271.         out_loc(p);
  1272.         return;
  1273.  
  1274.     default:
  1275.         g_error(p, "out_arg: internal: bad node\n");
  1276.         printf("bad node %p: c_code=%d %s\n",
  1277.             p, p -> c_code, ps_tok(p->c_code));
  1278.     }
  1279. }
  1280.  
  1281. /*
  1282.     Output a loc node.
  1283. */
  1284. static void
  1285. out_loc(register struct node *p)
  1286. {
  1287.     char buffer[40];
  1288.     register char mode;
  1289.     register struct st_node *id;
  1290.  
  1291.     mode = p -> n_mode;
  1292.     if (mode == VALUE_MODE) {
  1293.         if (!p -> n_reg1) {
  1294.             syscput('#');
  1295.         }
  1296.     }
  1297.     if (id = p -> n_cid) {
  1298.         syssput(id -> st_alias);
  1299.     }
  1300.     if (p -> n_const || (!p -> n_cid && 
  1301.     ((p -> n_reg1 && p -> n_reg2) || (!p -> n_reg1 && !p -> n_reg2)) ) ) {
  1302.         if (p -> n_cid && p -> n_const >= 0) {
  1303.             syscput('+');
  1304.         }
  1305.         convl2s(p -> n_const, buffer);
  1306.         syssput(buffer);
  1307.     }
  1308.     if (mode && p -> n_reg1) {
  1309.         if (mode == EAPRD_MODE) {
  1310.             syscput('-');
  1311.         }
  1312.         syscput('(');
  1313.     }
  1314.  
  1315.     if (p -> n_reg1) {
  1316.         syssput(arp_tab [p -> n_reg1]);
  1317.  
  1318.         if (p -> n_reg2) {
  1319.             syscput(',');
  1320.             syssput(arp_tab [p -> n_reg2]);
  1321.             switch (p -> n_scflag) {
  1322.             case X2_WORD:
  1323.                 syssput(".w");
  1324.                 break;
  1325.             case X2_LONG:
  1326.                 syssput(".l");
  1327.                 break;
  1328.             default:
  1329.                 g_error(p, "out_loc: internal: unscaled reg2\n");
  1330.                 break;
  1331.             case 0:
  1332.             case X2_OK:
  1333.                 ;
  1334.             }
  1335.         }
  1336.     }
  1337.     if (mode && p -> n_reg1) {
  1338.         syscput(')');
  1339.         if (mode == EAPSI_MODE) {
  1340.             syscput('+');
  1341.         }
  1342.     }
  1343. }
  1344.  
  1345. char *
  1346. ps_tok(int tok)
  1347. {
  1348.     if (tok > 0 && tok <= LABEL_TOK) {
  1349.         return kp_tab[tok];
  1350.     }
  1351.     else {
  1352.         return "<bad TOKEN>";
  1353.     }
  1354. }
  1355.